<template>
  <div class="container">
    <a-divider orientation="left" orientation-margin="0px">工具箱水印溯源任务</a-divider>

    <a-row class="toolbox-left">
      <a-col :span="24" v-if="toolboxcom">
        <a-form :model="formState" name="validate_other" v-bind="formItemLayout" @finish-failed="onFinishFailed" @finish="onFinish" :rules="formRules">
          <a-form-item>
            <a-form-item name="dragger" noStyle>
              <a-upload-dragger
                v-model:fileList="fileList"
                name="file"
                :multiple="false"
                :customRequest="handleMultipartUpload"
                :beforeUpload="beforeUpload"
                :headers="uploadHeaders"
                @change="handleChange"
                @drop="handleDrop"
              >
                <p class="ant-upload-drag-icon">
                  <InboxOutlined />
                </p>
                <p class="ant-upload-text">点击或将文件拖拽到这里上传</p>
                <p class="ant-upload-hint" style="padding: 10px 14px 0">
                  支持对以下文件类型溯源：DMP、TXT、CSV、XLSX、XLS、DEL、DOC、DOCX、PPT、PPTX、PDF、DCM、PNG、JPG、JPEG、BMP、E，及含上述格式的 ZIP/TAR/TAR.GZ 压缩包。​
                </p>
              </a-upload-dragger>
            </a-form-item>
          </a-form-item>

          <a-form-item style="text-align: center">
            <a-button type="primary" htmlType="submit" size="large" :disabled="isSubmitting || uploadStatus !== 'completed'">文件溯源</a-button>
          </a-form-item>
        </a-form>
      </a-col>

      <a-col :span="24" class="toolboxbut" v-if="toolboxbut">
        <!--正在处理文件-->
        <a-space v-if="loading" class="loading">
          <a-spin tip="文件正在处理中..." size="large" />
        </a-space>

        <!--开始下载-->
        <a-result status="success" title="文件溯源完毕" :subTitle="subTitle" v-if="dowbut">
          <template #extra>
            水印内容
            <br />
            <b style="font-size: 2rem; background: #eef4ff; padding: 1rem; display: block; margin-top: 10px">{{ messages }}</b>
          </template>
        </a-result>
      </a-col>

      <a-col :span="24" class="toolboxend" v-if="toolboxend">
        <a-button size="large" @click="goToToolbox">返回工具箱</a-button>
      </a-col>
    </a-row>

    <a-row>
      <a-col :span="24" class="zi_bottom">
        <p>工具对上传的文件进行水印溯源分析，可查看已添加水印信息，使用步骤如下：</p>
        <p>（1）上传文件</p>
        <p>（2）点击【文件溯源】启动溯源</p>
        <p>（3）处理完成后显示水印信息</p>
      </a-col>
    </a-row>
  </div>
</template>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import { InboxOutlined, DownloadOutlined, BookFilled } from '@ant-design/icons-vue'
import type { UploadChangeParam, UploadFile, UploadRequestOption } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { useUserStoreWithOut } from '@/stores/modules/user'
import { dmsMaskCenterApi } from '@/api/dms-mask-center'
import { http } from '@/utils/http'
import type { ApiResult } from '@/types/app'
import { useRouter } from 'vue-router'
// 文件列表和上传状态管理
const fileList = ref<UploadFile[]>([])
const subTitle = ref('')
const namekey = ref('')
const wataskid = ref('')
const loading = ref(false)
const dowbut = ref(false)
const isSubmitting = ref(false)
const uploadStatus = ref<'idle' | 'uploading' | 'completed' | 'failed'>('idle')
const uploadProgress = ref(0)
const currentFileId = ref('')
// 新增：存储从notice接口获取的token
const uploadToken = ref('')
const filePath = ref('')
const messages = ref('暂无内容')
const toolboxcom = ref(true)
const toolboxbut = ref(false)
const toolboxend = ref(false)
// 分片上传配置
const sliceSize = 5 * 1024 * 1024 // 5MB 分片大小
const noticeApi = '/dms-mask-center/api/v1/trace/upload/notice'
const chunkApi = '/dms-mask-center/api/v1/trace/upload/chunk'

const formRules = {
  // 文件上传校验：必须上传文件
  file: [
    {
      required: true,
      message: '请上传文件',
      trigger: ['change', 'submit']
    }
  ]
}

// 生成文件唯一标识
const generateFileId = (file: File) => {
  return `${file.name}-${file.size}-${file.lastModified}-${Date.now()}`
}

// 处理分片上传
const handleMultipartUpload = async (options: UploadRequestOption) => {
  const file = options.file as File
  const fileId = generateFileId(file)
  currentFileId.value = fileId
  const chunkSize = Math.ceil(file.size / sliceSize)

  try {
    uploadStatus.value = 'uploading'
    uploadProgress.value = 0

    // 1. 调用通知接口并获取token
    const { success, token } = await callNoticeApi(file, fileId, chunkSize)

    // 保存获取到的token
    uploadToken.value = token
    if (!uploadToken.value) {
      throw new Error('未从通知接口获取到token')
    }

    // 2. 分片上传（携带token）
    for (let chunkIndex = 0; chunkIndex < chunkSize; chunkIndex++) {
      const start = chunkIndex * sliceSize
      const end = Math.min(start + sliceSize, file.size)
      const chunk = file.slice(start, end)

      const chunkSuccess = await uploadSingleChunk({
        chunk,
        chunkIndex,
        chunkSize,
        filename: file.name,
        token: uploadToken.value // 传递token
      })

      // 更新进度
      uploadProgress.value = Math.floor(((chunkIndex + 1) / chunkSize) * 100)
    }

    // 3. 上传完成处理
    uploadStatus.value = 'completed'
    options.onSuccess({ fileId, filename: file.name })
    message.success('文件上传成功！')
    namekey.value = fileId // 使用fileId作为标识
    subTitle.value = file.name
  } catch (error) {
    uploadStatus.value = 'failed'
    options.onError(error as Error)
    message.error(`上传失败：${(error as Error).message}`)
  }
}

// 调用通知接口（获取token）
const callNoticeApi = async (file: File, fileId: string, chunkSize: number) => {
  try {
    const response = await http.post<ApiResult<{ token: string }>>({
      url: noticeApi,
      data: {
        filename: file.name,
        fileSize: file.size,
        sliceSize,
        chunkSize
      }
    })

    // 返回成功状态和token
    return {
      success: response.success,
      token: response.data?.token || ''
    }
  } catch (error) {
    console.error('通知接口调用失败：', error)
    return {
      success: false,
      token: ''
    }
  }
}

// 上传单个分片（携带token）
const uploadSingleChunk = async ({
  chunk,
  chunkIndex,
  chunkSize,
  filename,
  token
}: {
  chunk: Blob
  chunkIndex: number
  chunkSize: number
  filename: string
  token: string // 新增token参数
}) => {
  try {
    const formData = new FormData()
    formData.append('file', chunk, `${filename}-${chunkIndex}`)
    formData.append('chunkIndex', chunkIndex.toString())
    formData.append('chunkSize', chunkSize.toString())
    formData.append('filename', filename)
    formData.append('token', token) // 携带token参数

    const response = await http.post<ApiResult<any>>({
      url: chunkApi,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    filePath.value = response.data?.filePath
    return response.success
  } catch (error) {
    console.error(`分片 ${chunkIndex} 上传失败：`, error)
    return false
  }
}

// 上传状态变更处理
const handleChange = (info: UploadChangeParam) => {
  console.log('上传状态变更：', info)
  // 清空文件列表时重置状态
  if (info.fileList.length === 0) {
    uploadStatus.value = 'idle'
    uploadProgress.value = 0
    namekey.value = ''
    subTitle.value = ''
    uploadToken.value = '' // 清空token
  }
}

// 上传前校验
const beforeUpload = (file: UploadFile) => {
  // 检查文件数量
  if (fileList.value.length >= 1) {
    message.warning('只能上传一个文件，请先删除已上传的文件！')
    return false
  }

  // 检查文件类型
  const allowedTypes = ['dmp', 'txt', 'csv', 'xlsx', 'xls', 'del', 'doc', 'docx', 'ppt', 'pptx', 'pdf', 'dcm', 'png', 'jpg', 'jpeg', 'bmp', 'e', 'zip', '7z', 'tar.gz', 'tar', 'gz', 'dt']
  const fileExt = file.name.split('.').pop()?.toLowerCase() || ''
  if (!allowedTypes.includes(fileExt)) {
    message.warning(`不支持的文件类型：.${fileExt}`)
    return false
  }

  // 检查文件大小（最大1GB）
  const maxSize = 1024 * 1024 * 1024
  if (file.size! > maxSize) {
    message.warning('文件大小不能超过1GB')
    return false
  }

  return true
}

function handleDrop(e: DragEvent) {
  console.log(e)
}

// 请求头
const uploadHeaders = {
  Authorization: `Bearer ${useUserStoreWithOut().getToken()}`
}

const formState = reactive<Record<string, any>>({
  group: ''
})

// 提交执行
const onFinish = (values: any) => {
  if (fileList.value.length <= 0 || uploadStatus.value !== 'completed') {
    message.error('请先完成文件上传！')
    return false
  }
  messages.value = ''
  // 按钮禁用
  isSubmitting.value = true
  dowbut.value = false
  toolboxcom.value = false
  loading.value = true
  toolboxbut.value = true
  toolboxend.value = true

  const formData = new FormData()
  // 2. 添加表单数据（键名需与后端接口参数一致）
  formData.append('fileName', subTitle.value)
  formData.append('filePath', filePath.value)
  formData.append('fileEncoding', 'UTF-8')

  dmsMaskCenterApi
    .postTraceability({
      data: formData, // 直接传入FormData对象
      headers: {
        // 显式指定内容类型为multipart/form-data（部分http工具需要）
        'Content-Type': 'multipart/form-data'
      }
    })
    .then((response) => {
      wataskid.value = response.data.id

      // 轮询检查处理结果
      setInterval(() => {
        dmsMaskCenterApi
          .postTraceabilityline({})
          .then((response) => {
            if (response.data[0].traceStatus == 'FAILED') {
              messages.value = response.data[0].message
            } else {
              messages.value = response.data[0].watermarkContentList[0]
            }
            // console.log(response.data[0].watermarkContentList[0]);
            loading.value = false
            dowbut.value = true
            isSubmitting.value = false
          })
          .catch((error) => {})
      }, 12000)
    })
    .catch((error) => {
      message.error('溯源处理失败')
      loading.value = false
      isSubmitting.value = false
    })
}

const onFinishFailed = (errorInfo: any) => {
  console.log('提交失败:', errorInfo)
}

// 下载文件
const postDownload = () => {
  // 实现下载逻辑
  console.log('下载文件，任务ID：', wataskid.value)
}

const router = useRouter()
const goToToolbox = () => {
  // 使用 router.push 跳转到指定路由
  location.reload()
}
</script>

<style scoped>
.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}
.form-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}
.ant-form-item .ant-form-item-label > label {
  font-size: 16px;
}
.ant-upload-wrapper .ant-upload-drag {
  padding: 7vh 0;
}
:where(.css-dev-only-do-not-override-10npqub).ant-upload-wrapper .ant-upload-drag p.ant-upload-drag-icon .anticon {
  font-size: 7rem;
}
:where(.css-dev-only-do-not-override-10npqub).ant-upload-wrapper .ant-upload-drag p.ant-upload-text {
  color: #1890ff;
}
.container .zi_bottom {
  border-top: solid 10px #eef4ff;
  padding: 1rem 0;
}
.ant-result .ant-result-title {
  color: #1890ff;
  font-size: 18px;
}
.ant-result {
  padding-top: 7vh;
}
.container .toolboxbut {
  border: 1px dashed #d9d9d9;
  text-align: center;
  min-height: 42vh;
}
.container .toolboxbut .loading {
  padding: 18vh;
}
.container .toolboxend {
  text-align: center;
  margin: 28px 0;
}
.ant-result .ant-result-extra {
  margin-top: 12px;
}
.zi_bottom h1 {
  font-size: 16px;
}
.zi_bottom p {
  color: #999;
}
</style>
